﻿#region Using Statements
using System;
using System.Threading;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.GamerServices;
using Lidgren.Network;
using Networking;
#endregion

namespace GameNetworked
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Color BackColor;
        Texture2D texture;
        Client client;

        public Game1()
            : base()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            BackColor = Color.Red;
            client = new Client("127.0.0.1", 7777, LogLevel.All);
            Exiting += Game1_Exiting;
        }

        void Game1_Exiting(object sender, EventArgs e)
        {
            client.Disconnect();
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            client.Connect();
            client.OnJoin += client_OnJoin;
            client.OnReceivePlayerSyncData += client_OnReceivePlayerSyncData;

            base.Initialize();
        }

        void client_OnReceivePlayerSyncData(int playerkey, SyncDataType syncdatatype, NetIncomingMessage incmsg)
        {
            Console.WriteLine("Received sync data " + syncdatatype.ToString() + " from player key " + playerkey.ToString());

            switch (syncdatatype)
            {
                case SyncDataType.Position:

                    float xPos = incmsg.ReadFloat();
                    client.Players[playerkey].PosX += xPos;
                    break;
            }
        }

        void client_OnJoin(int playerkey)
        {
            Console.WriteLine("You joined and received key " + playerkey.ToString());
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            texture = Content.Load<Texture2D>("player.png");
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

           
            float xPos = 0.0f;

            if (Keyboard.GetState().IsKeyDown(Keys.Left))
                xPos = -1.0f;
            else if (Keyboard.GetState().IsKeyDown(Keys.Right))
                xPos = 1.0f;
            else
                xPos = 0.0f;

            if (xPos != 0)
            {
                client.Me.PosX += xPos;
                NetOutgoingMessage outmsg;
                outmsg = client.BeginSendPlayerData(SyncDataType.Position);
                outmsg.Write(xPos);
                client.EndSendPlayerData(outmsg);
            }

            client.NetUpdate();

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(BackColor);

            spriteBatch.Begin();
            foreach (KeyValuePair<int, Player> player in client.Players)
                player.Value.Draw(texture, spriteBatch);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}
